package data
{
	import com.maclema.mysql.MySqlToken;
	import com.maclema.mysql.ResultSet;
	
	import controls.DataHub;
	import controls.DataRequestor;
	import controls.events.ServiceEvent;
	
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;
	
	import mx.collections.ArrayCollection;
	
	[Event(name="programLoaded", source="controls.event.ServiceEvent")]
	
	public class Degree extends EventDispatcher
	{
		// --------------- Private Variables ------------------- //
		private var _name:String;
		private var _college:String;
		private var _colleges:Array;
		private var _jointDegree:Boolean;
		private var _id:int;
		private var _type:String;
		
		private var _classGroups:Dictionary;		
		
		private var hub:DataHub = DataHub.instance;
		private var requestor:DataRequestor = DataRequestor.instance;
		
		private var pendingClassRequestCount:int;
		private var pending:Dictionary;
		// --------------- END Private Variables ------------------- //
		
		// --------------- Public Variables ---------------- //
		public var totalCredits:int;
		// --------------- END Public Variables ---------------- //
		
		public function Degree(row:Object = null)
		{
			pendingClassRequestCount = 0;
			pending = new Dictionary();
			
			jointDegree = false;
			colleges = [];
			classGroups = new Dictionary();
			classGroups['required'] = new ClassGroup();
			classGroups['required'].name = "Required";
			
			if(row != null)
			{
				name = row.degreeName;
				college = row.college;
				id = row.ID;
				type = DegreeType.toType(row.type);
			}
		}
		
		// --------------- Data Loading and Parsing ----------------- //
		public function getClassInformation():void
		{
			requestor.getDegreeProgram(this, parseDegree);
		}
		
		private function parseDegree(sqlData:Object, token:MySqlToken):void
		{
			var rs:ResultSet = sqlData as ResultSet;
			
			var rows:ArrayCollection = rs.getRows();
			pendingClassRequestCount = rows.length;
			
			for each(var row:Object in rs.getRows())
				doClassRequests(row);
		}
		
		private function doClassRequests(courseInfo:Object):void
		{
			if(courseInfo.numGroup == 0)
				requestor.getDegreeClass(courseInfo, this, parseClass);
			else
			{
				var group:ClassGroup = new ClassGroup(courseInfo)
				pending[group.id] = group;
				group.addEventListener(ServiceEvent.PROGRAM_LOADED, onCoursesReady);
				this.addClassGroup(group);
			}
		}
		
		private function parseClass(sqlData:Object, token:MySqlToken):void
		{
			var rs:ResultSet = sqlData as ResultSet;
			
			for each(var row:Object in rs.getRows())
			{
				var course:Course = new Course(row);
				pending[course.title] = course;
				course.addEventListener(ServiceEvent.COURSES_LOADED, onCoursesReady);
				this.addClass(course);
			}
		}
		
		private function onCoursesReady(evt:ServiceEvent):void
		{
			pendingClassRequestCount --;
			if(evt.data is Course)
				pending[evt.data.title] = false;
			else if(evt.data is ClassGroup)
				pending[evt.data.id] = false;
				
			if(pendingClassRequestCount == 0)
			{
				hub.updateDegree(this);
				this.dispatchEvent(new ServiceEvent(ServiceEvent.PROGRAM_LOADED, this));
			}
		}
		// --------------- END Data Loading and Parsing ----------------- //
		
		// --------------- Class Getting Functions ----------------- //
		public function addClassGroup(group:ClassGroup):void
		{
			totalCredits += group.creditsRequired;
			classGroups[group.id] = group;
		}
		
		public function addClass(course:Course):void
		{
			totalCredits += course.credits;
			classGroups['required'].addCourse(course);
			classGroups['required'].creditsRequired += course.credits;
		}
		
		public function hasCourseById(courseId:int):Course
		{
			for each(var group:ClassGroup in classGroups)
			{
				for each(var course:Course in group.classes)
				{
					if(course.id == courseId)
						return course;
				}
			}
			return null;
		}
		// --------------- END Class Getting Functions ----------------- //
		
		// ----------------- Accessors ------------------ //
		public function get name():String
		{
			return _name;
		}
		public function set name(value:String):void
		{
			_name = value;
		}
		
		public function get classGroups():Dictionary
		{
			return _classGroups;
		}
		public function set classGroups(value:Dictionary):void
		{
			_classGroups = value;
		}
		
		public function get type():String
		{
			return _type;
		}
		public function set type(value:String):void
		{
			_type = value;
		}
		
		public function get id():int
		{
			return _id;
		}
		public function set id(value:int):void
		{
			_id = value;
		}
		
		public function get college():String
		{
			return _college;
		}
		public function set college(value:String):void
		{
			_college = value;
		}
		
		public function get colleges():Array
		{
			return _colleges;
		}
		public function set colleges(value:Array):void
		{
			_colleges = value;
		}
		
		public function get jointDegree():Boolean
		{
			return _jointDegree;
		}
		public function set jointDegree(value:Boolean):void
		{
			_jointDegree = value;
		}
		// ----------------- END Accessors ------------------ //
	}
}